#include "vsf.h"

#include "btstack_config.h"
#include "btstack_debug.h"
#include "hci.h"
#include "hci_transport.h"

struct hci_transport_h2_param_t
{
	bool opened;
	void *dev;
	void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
} static hci_transport_h2_param;

static int hci_transport_h2_open(void)
{
	if (hci_transport_h2_param.dev)
	{
		hci_transport_h2_param.opened = true;
		return 0;
	}
	return -1;
}

static int hci_transport_h2_close(void)
{
	hci_transport_h2_param.opened = false;
	return 0;
}

static void hci_transport_h2_register_packet_handler(
		void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size))
{
	hci_transport_h2_param.packet_handler = handler;
}

static int hci_transport_h2_can_send_packet_now(uint8_t packet_type)
{
	if (hci_transport_h2_param.opened)
		return vsfusbh_bthci_cansend(hci_transport_h2_param.dev, packet_type);
	return 0;
}

static int hci_transport_h2_send_packet(uint8_t packet_type, uint8_t *packet, int size)
{
	if (hci_transport_h2_param.opened)
		return vsfusbh_bthci_send(hci_transport_h2_param.dev, packet_type, packet, size);
	return 0;
}

static void hci_transport_h2_on_new(void *dev, struct vsfusbh_device_id_t *id)
{
	if (!hci_transport_h2_param.dev)
		hci_transport_h2_param.dev = dev;
}

static void hci_transport_h2_on_del(void *dev)
{
	if (dev == hci_transport_h2_param.dev)
		hci_transport_h2_param.dev = NULL;
}

static void hci_transport_h2_on_packet(void *dev, uint8_t type, uint8_t *packet, uint16_t size)
{
	const uint8_t event[] = {HCI_EVENT_TRANSPORT_PACKET_SENT, 0};

	if (hci_transport_h2_param.opened && (dev == hci_transport_h2_param.dev) &&
		hci_transport_h2_param.packet_handler)
	{
		if (type & 0x80)
		{
			type = HCI_EVENT_PACKET;
			packet = (uint8_t *)event;
			size = sizeof(event);
		}
		hci_transport_h2_param.packet_handler(type, packet, size);
	}
}

static void hci_transport_h2_init(const void *transport_config)
{
	if (transport_config != NULL)
		hci_transport_h2_on_new((void *)transport_config, NULL);
	vsfusbh_bthci_config_cb(hci_transport_h2_on_new, hci_transport_h2_on_del,
			hci_transport_h2_on_packet);
}

static const hci_transport_t hci_transport_h2 =
{
	.name = "H2_VSF",
	.init = hci_transport_h2_init,
	.open = hci_transport_h2_open,
	.close = hci_transport_h2_close,
	.register_packet_handler = hci_transport_h2_register_packet_handler,
	.can_send_packet_now = hci_transport_h2_can_send_packet_now,
	.send_packet = hci_transport_h2_send_packet,
};

const hci_transport_t * hci_transport_usb_instance(void)
{
	return &hci_transport_h2;
}

